﻿using Newtonsoft.Json;
using QDPay.Bus.domain.json;
using QDPay.Bus.domain.pay;
using QDPay.Bus.util;
using QDPay.WxSdk;
using QDPay.WxSdk.Domain.pay;
using System;
using System.Collections.Generic;
using System.Threading;

namespace QDPay.Bus
{
    public class QDPays : BusinessBase
    {
        /// <summary>
        /// 校验支付结果
        /// </summary>
        /// <param name="json">支付返回结果</param>
        /// <param name="createUid">商家uid</param>
        /// <returns></returns>
        public string CheckPay(JsonBase<PayResponse> json, int createUid)
        {
            if (!IsSuccess(json))
                return "支付失败:" + json.Message;

            var pay = json.Data;
            if (pay == null || string.IsNullOrEmpty(pay.out_trade_no))
                return "接口错误,返回数据解析失败";

            if (pay.trade_state == "SUCCESS")
                return "支付成功";

            int queryTimes = 10;    //计数器
            bool isSuccess = false;
            var msg = string.Empty;

            //支付结果未知状态时，每隔一段时间查询一次订单，共查询10次
            while (queryTimes-- > 0)
            {
                var orderJson = RefreshPay(pay.out_trade_no, createUid);
                if (!IsSuccess(orderJson))
                {
                    msg = orderJson.Message; break;                 //接口错误, 支付失败
                }

                var order = orderJson.Data;
                if (order.err_code == "ORDERNOTEXIST")
                {
                    msg = order.err_code_des; break;                //含微信错误码，则直接支付失败
                }

                if (order.trade_state == "SUCCESS")
                {
                    isSuccess = true;
                    msg = "支付成功"; break;                        //支付成功
                }
                else if (order.trade_state == "CLOSED")
                {
                    msg = "支付已关闭"; break;
                }
                else if (order.trade_state == "USERPAYING")
                {
                    Thread.Sleep(2000);         //支付中, 请等待
                }
                else
                {
                    Thread.Sleep(2000);         //其他状态，则等待2s后继续
                }
            }

            //多次刷新后,支付失败，调用取消支付接口
            if (!isSuccess)
            {
                msg = "交易失败, 取消支付";
                var cacelJson = CacelPay(pay.out_trade_no, createUid);

                LogUtil.WriteLog(string.Format("pay 撤销支付: out_trade_no:{0}, createuid={1},\r\n {2}",
                    pay.out_trade_no, createUid, cacelJson));
            }
            return msg;
        }

        /// <summary>
        /// 发起支付
        /// </summary>
        /// <param name="createUid">商户id</param>
        /// <param name="oid">订单id</param>
        /// <param name="money">付款金额</param>
        /// <param name="code">微信授权码</param>
        /// <returns></returns>
        public JsonBase<PayResponse> MicroPay(int createUid, int oid, decimal money, string code)
        {
            var url = string.Format("{0}/api/wechat/micropay?createUid={1}&oid={2}&money={3}&auth_code={4}",
                        ApiConfig.Domain, createUid, oid, money, code);
            var html = RestHttp.Get(url);
            var json = DeserializeObject<JsonBase<PayResponse>>(html);
            return json;
        }

        /// <summary>
        /// 授权码获取用户uid
        /// </summary>
        /// <param name="createUid">商户id</param>
        /// <param name="code">授权码</param>
        /// <returns></returns>
        public int CodeToUid(int createUid, string code)
        {
            int uid = 0;
            var url = string.Format("{0}/api/wechat/AuthCodeToUid?createUid={1}&auth_code={2}",
                        ApiConfig.Domain, createUid, code);
            var html = RestHttp.Get(url);
            var json = DeserializeObject<JsonBase<string>>(html);
            if (IsSuccess(json))
                int.TryParse(json.Data, out uid);
            return uid;
        }

        /// <summary>
        /// 刷新支付订单
        /// </summary>
        /// <param name="out_trade_no"></param>
        /// <returns></returns>
        public JsonBase<PayResponse> RefreshPay(string out_trade_no, int createUid)
        {
            var url = string.Format("{0}/api/wechat/RefreshPay?out_trade_no={1}&createUid={2}&isCheck=1&trade_type={2}",
                        ApiConfig.Domain, out_trade_no, createUid, "MICROPAY");
            var html = RestHttp.Get(url);
            var json = DeserializeObject<JsonBase<PayResponse>>(html);
            return json;
        }

        /// <summary>
        /// 取消支付
        /// </summary>
        /// <param name="out_trade_no"></param>
        public object CacelPay(string out_trade_no, int createUid)
        {
            var url = string.Format("{0}/api/wechat/CacelMicroPay?out_trade_no={1}&createUid={2}",
                        ApiConfig.Domain, out_trade_no, createUid);
            var html = RestHttp.Get(url);
            return html;
        }


        #region 刷脸支付
        public FaceAuth GetFaceAuthhInfo(int createUid, string rawData)
        {
            var url = string.Format("{0}/api/wechat/GetFaceAuthInfo?createUid={1}&rawdata={2}", ApiConfig.Domain, createUid,
                        System.Web.HttpUtility.UrlEncode(rawData));
            var html = RestHttp.Get(url);
            var json = DeserializeObject<JsonBase<FaceAuth>>(html);

            if (IsSuccess(json))
                return json.Data;
            return null;
        }

        public FaceCode GetFaceCode(FaceCodeInput codeInput)
        {
            var json = FaceSDK.GetFaceCode(codeInput);
            var faceCode = JsonConvert.DeserializeObject<FaceCode>(json);
            return faceCode;
        }

        public JsonBase<PayResponse> FacePay(int createUid, int oid, decimal money, string code)
        {
            var url = string.Format("{0}/api/wechat/facepay?createUid={1}&oid={2}&money={3}&face_code={4}",
                        ApiConfig.Domain, createUid, oid, money, code);
            var html = RestHttp.Get(url);
            var json = DeserializeObject<JsonBase<PayResponse>>(html);
            return json;
        }
        #endregion
    }
}
